#include<stdio.h>
#include<stdlib.h>
#include<stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include<errno.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>

#define SetBit(x, y) (x |= 1<<y)
#define GetBit(x,y) ((x>>y) & 1)

#define N 128
#define MAXCLIENT 3

#define ERRLOG(errmsg) do{\
                                                                perror(errmsg);\
                                                                printf("file : %s, func: %s, line : %d", __FILE__, __func__, __LINE__);\
                                                                exit(-1);\
                                                         }while(0);

int main(int argc, char const *argv[]){
    if(argc != 3){
        fprintf(stderr, "Usage %s <ip> <port>\n", argv[0]);
        exit(-1);
    }

    int sockfd = -1;
    int acceptfd[MAXCLIENT];
    struct sockaddr_in servaddr, clientaddr[MAXCLIENT];
    unsigned int closefd = 0;
    socklen_t addrlen = sizeof(servaddr);
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
        ERRLOG("socket error");
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    servaddr.sin_port = htons(atoi(argv[2]));

    if(bind(sockfd, (struct sockaddr *)&servaddr, addrlen) == -1){
        ERRLOG("bind error");
    }

    if(listen(sockfd, 5) == -1){
        ERRLOG("listen error");
    }

    int i = 0;
    for(i = 0; i < MAXCLIENT; i++){
        if((acceptfd[i] = accept(sockfd, (struct sockaddr *)&clientaddr[i], &addrlen)) == -1){
            ERRLOG("accept error");
        }
        printf("Client : [%s : %d] Linked\n", inet_ntoa(clientaddr[i].sin_addr), ntohs(clientaddr[i].sin_port));
    }

    char buf[N] = {0};
    ssize_t bytes;
    while(1){
        for(i = 0; i < MAXCLIENT; i++){
            //判断
            if(GetBit(closefd, i)){
                continue;
            }
            if((bytes = recv(acceptfd[i], buf, N, MSG_DONTWAIT)) == -1){
                if(errno == 11){
                    continue;
                }else{
                    ERRLOG("recv error");
                }
            }else{
                if(bytes == 0 || strcmp(buf, "**QUIT**") == 0){
                    printf("Client : [%s : %d] Quit\n", inet_ntoa(clientaddr[i].sin_addr), ntohs(clientaddr[i].sin_port));
                    //设置
                    SetBit(closefd, i);
                    close(acceptfd[i]);
                    continue;
                }
                printf("Client : [%s : %d] Says : %s\n", inet_ntoa(clientaddr[i].sin_addr), ntohs(clientaddr[i].sin_port), buf);
                strcat(buf, "^_^");
                if(send(acceptfd[i], buf, N, 0) == -1){
                    ERRLOG("send error");
                }
            }
        }
    }
    return 0;
}